using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;

using ZoneFiveSoftware.Common.Data;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.GPS;
using ZoneFiveSoftware.Common.Visuals;
//using BENBUN.ExportCRS.Xml.Topografix.Gpx11;
using BENBUN.ExportCRS.Xml.Garmin;

namespace BENBUN.ExportCRS
{
    partial class  ExportActivityToCRSAction : IAction
    {
        public ExportActivityToCRSAction(IActivity activity)
        {
            this.activity = activity;
        }

        #region IAction Members

        public bool Enabled
        {
            get { return activity != null && activity.GPSRoute.Count > 0; }
        }

        public bool HasMenuArrow
        {
            get { return false; }
        }

        public Image Image
        {
            get { return Properties.Resources.Image_16_Export; }
        }

        public void Refresh()
        {
        }

        public void Run(Rectangle rectButton)
        {
            //Export("C:\\Documents and Settings\\Richard\\My Documents\\test.crs");
            FileDialog dialog = new SaveFileDialog();
            dialog.Filter = "CRS Route File (*.crs)|*.crs|All files|*.*";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    Export(dialog.FileName);
                    MessageBox.Show("The CRS Extract file has been created", "Export Complete", MessageBoxButtons.OK);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        public string Title
        {
            get { return Properties.Resources.Edit_ExportRouteToCRSAction_Text; }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        private void Export(string filename)
        {
            // Build the xml data.   
            List<CoursePoint_t> coursePoints = new List<CoursePoint_t>();

            //double aa = BenbunPlugin.Instance.summitSize;
            //aa++;

            TrainingCenterDatabase_t crsExport = new TrainingCenterDatabase_t();
            Courses_t crsCourses = new Courses_t();
            crsExport.Courses = crsCourses;
            CourseFolder_t crsCourseFolder = new CourseFolder_t();
            crsCourseFolder.Name = "Exported from SportTracks Activity with ExportCRS";
            crsExport.Courses.CourseFolder = crsCourseFolder;

            Course_t crsCourse = new Course_t();

            if (BenbunPlugin.Instance.nameSourceLocation == "location")
            {
                crsCourse.Name = activity.Location;
                if (crsCourse.Name.Trim() == "")
                {
                    crsCourse.Name = activity.Name;
                }
            }
            else
            {
                crsCourse.Name = activity.Name;
                if (crsCourse.Name.Trim() == "")
                {
                    crsCourse.Name = activity.Location;
                }
            }


            if (crsCourse.Name.Trim() == "")
            {
                crsCourse.Name = "Course Name";
            }

            if (crsCourse.Name.Length > 15)
            {
                crsCourse.Name = crsCourse.Name.Substring(0, 15);
            }

            
            
            CourseLap_t crsLap = new CourseLap_t();
            crsLap.TotalTimeSeconds = activity.GPSRoute.TotalElapsedSeconds;
            crsLap.DistanceMeters = activity.GPSRoute.TotalDistanceMeters;
            crsLap.Intensity = Intensity_t.Active;
            crsLap.Cadence = (System.Byte)(0);
            crsLap.CadenceSpecified = true;

            Position_t crsBeginPosition = new Position_t();
            Position_t crsEndPosition = new Position_t();
            activity.Notes = activity.Notes;
            IGPSRoute GPSRouteLocal = activity.GPSRoute;

            ITimeValueEntry<IGPSPoint> GPSStartPoint = GPSRouteLocal[0];
            ITimeValueEntry<IGPSPoint> GPSEndPoint = GPSRouteLocal[GPSRouteLocal.Count - 1];

            crsBeginPosition.LatitudeDegrees = GPSStartPoint.Value.LatitudeDegrees;
            crsBeginPosition.LongitudeDegrees = GPSStartPoint.Value.LongitudeDegrees;
   
            crsEndPosition.LatitudeDegrees = GPSEndPoint.Value.LatitudeDegrees;
            crsEndPosition.LongitudeDegrees = GPSEndPoint.Value.LongitudeDegrees;

            //
            // Potential to add maximum and average heart rate to this class
            // at a later date.
            //
            crsLap.BeginPosition = crsBeginPosition;
            crsLap.BeginAltitudeMeters = GPSStartPoint.Value.ElevationMeters;
            crsLap.BeginAltitudeMetersSpecified = true;
            crsLap.EndPosition = crsEndPosition;
            crsLap.EndAltitudeMeters = GPSEndPoint.Value.ElevationMeters;
            crsLap.EndAltitudeMetersSpecified = true;
            crsCourse.Lap = new CourseLap_t[] { crsLap };

            //
            // Deal with the trackpoints
            Track_t crsTrack = new Track_t();
            int trackPointIndex = 0;
            Trackpoint_t[] crsTrackpoint = new Trackpoint_t[GPSRouteLocal.Count];
            ITimeValueEntry<IGPSPoint> priorEntry = null;
            double totalDistance = 0;
            foreach (ITimeValueEntry<IGPSPoint> entry in activity.GPSRoute)
            {
                if (priorEntry != null)
                {
                    totalDistance += priorEntry.Value.DistanceMetersToPoint(entry.Value);
                }
                crsTrackpoint[trackPointIndex] = new Trackpoint_t();
                crsTrackpoint[trackPointIndex].Time = activity.StartTime.AddSeconds(entry.ElapsedSeconds);
                crsTrackpoint[trackPointIndex].Position = new Position_t();
                crsTrackpoint[trackPointIndex].Position.LatitudeDegrees = entry.Value.LatitudeDegrees;
                crsTrackpoint[trackPointIndex].Position.LongitudeDegrees = entry.Value.LongitudeDegrees;
                crsTrackpoint[trackPointIndex].AltitudeMeters = entry.Value.ElevationMeters;
                crsTrackpoint[trackPointIndex].AltitudeMetersSpecified = true;
                crsTrackpoint[trackPointIndex].DistanceMeters = totalDistance;
                crsTrackpoint[trackPointIndex].DistanceMetersSpecified = true;
                trackPointIndex++;
                priorEntry = entry;
            }

            crsTrack.Trackpoint = crsTrackpoint;
            crsCourse.Track = new Track_t[] { crsTrack };

            GPSUtils GPSUtilities = new GPSUtils();
            if (BenbunPlugin.Instance.doTurns)
            {
                coursePoints.AddRange(GPSUtilities.CreateTurnPoints(crsTrack.Trackpoint)); 
            }

            if (BenbunPlugin.Instance.doValleys)
            {
                coursePoints.AddRange(GPSUtilities.CreateValleys(crsTrack.Trackpoint));
            }

            if (BenbunPlugin.Instance.doSummits)
            {
                coursePoints.AddRange(GPSUtilities.CreateSummits(crsTrack.Trackpoint));
            }
            
           
            crsCourse.CoursePoint =  coursePoints.ToArray();
            crsExport.Courses.CourseFolder.Course = new Course_t[] { crsCourse };

            //// Save the crs file.
            XmlSerializer serializer = new XmlSerializer( crsExport.GetType() );
            TextWriter writer = new StreamWriter(filename);
            serializer.Serialize(writer, crsExport);
            writer.Close();
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        private int IndexOfFirstAltitude(Trackpoint_t[] track)
        {
            int start = 0;
            while (start < track.Length && !track[start].AltitudeMetersSpecified)
            {
                start++;
            }

            return start == track.Length ? -1 : start;
        }
        private IActivity activity = null;
    }
}
